package com.example.common.utils.permission;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;

import com.coszero.utilslibrary.utils.LogX;
import com.example.common.config.RequestCode;
import com.permissionx.guolindev.PermissionX;
import com.permissionx.guolindev.callback.ExplainReasonCallback;
import com.permissionx.guolindev.callback.ForwardToSettingsCallback;
import com.permissionx.guolindev.callback.RequestCallback;
import com.permissionx.guolindev.request.ExplainScope;
import com.permissionx.guolindev.request.ForwardScope;

import java.util.ArrayList;
import java.util.List;


/**
 * @author xmqian
 * @date 19-3-19
 * @desc 6.0动态权限请求，手动在所在界面使用#onRequestPermissionsResult()#进行回调
 * - 可进行单权限原生和依赖库申请
 * - 可进行多权限原生和依赖库申请
 * - 提供一次性申请权限列表进行申请
 */
public class PermissionHelper {
    private CallBack requestCallBack;
    private static final String TAG = "PermissionRequest";
    /**
     * 应用所需要的必要权限
     */
    public static String[] NEED_PERMISSIONS = new String[]{
            Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE, Manifest.permission.ACCESS_FINE_LOCATION
    };

    // <editor-fold desc="第三方库权限申请封装" defaultstate="collapsed">

    /**
     * 权限申请
     *
     * @param context 最好是Activity
     * @param permissions 需要申请的权限
     * @param requestCallBack 请求回调,传null就没有回调结果
     */
    @TargetApi(23)
    public static void request(FragmentActivity context, @Nullable CallBack requestCallBack, String[] permissions) {
        //小于API23(6.0)不需要申请,直接默认已申请权限
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            LogX.i(TAG, "当前API版本" + Build.VERSION.SDK_INT);
            if (requestCallBack != null) requestCallBack.requestSuccess();
            return;
        }
        PermissionX.init(context).permissions(permissions)
                .onExplainRequestReason(new ExplainReasonCallback() {
                    @Override
                    public void onExplainReason(ExplainScope scope, List<String> deniedList) {
                        //这里可以处理被拒绝的权限
                        scope.showRequestReasonDialog(deniedList, "请同意所需权限,否则将影响功能的正常使用", "我已明白");
                    }
                })
                .onForwardToSettings(new ForwardToSettingsCallback() {
                    @Override
                    public void onForwardToSettings(ForwardScope scope, List<String> deniedList) {
                        //这里可以处理被用户永久拒绝的权限
                        scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "我已明白", "取消");
                    }
                })
                .request(new RequestCallback() {
                    @Override
                    public void onResult(boolean allGranted, List<String> grantedList, List<String> deniedList) {
                        if (allGranted) {
                            //申请成功
                            if (requestCallBack != null) requestCallBack.requestSuccess();
                        } else {
                            //申请失败
                            LogX.e(TAG, "权限未全部申请成功");
                            if (requestCallBack instanceof CallBackFail) {
                                if (requestCallBack != null)
                                    ((CallBackFail) requestCallBack).requestFail();
                            }
                        }
                    }
                });
    }

    /**
     * 单权限申请
     */
    public static void requestSingle(FragmentActivity activity, String permission, CallBack requestCallBack) {
        request(activity, requestCallBack, new String[]{permission});
    }

    /**
     * 简易权限申请,一次性全部申请
     * 主要用于启动界面
     */
    public static void requestEasy(FragmentActivity activity, CallBack callBack) {
        request(activity, callBack, NEED_PERMISSIONS);
    }

    /**
     * 申请读写权限
     */
    public static void requestStorage(FragmentActivity activity, CallBack callBack) {
        request(activity, callBack, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
    }

    /**
     * 权限申请
     *
     * @param context 最好是Activity
     * @param permissions 需要申请的权限
     * @param requestCallBack 请求回调,传null就没有回调结果
     */
    @TargetApi(23)
    public static void request(Fragment context, @Nullable CallBack requestCallBack, String[] permissions) {
        //小于API23(6.0)不需要申请,直接默认已申请权限
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            LogX.i(TAG, "当前API版本" + Build.VERSION.SDK_INT);
            if (requestCallBack != null) requestCallBack.requestSuccess();
            return;
        }
        PermissionX.init(context).permissions(permissions)
                .onExplainRequestReason(new ExplainReasonCallback() {
                    @Override
                    public void onExplainReason(ExplainScope scope, List<String> deniedList) {
                        //这里可以处理被拒绝的权限
                        scope.showRequestReasonDialog(deniedList, "请同意所需权限,否则将影响功能的正常使用", "我已明白");
                    }
                })
                .onForwardToSettings(new ForwardToSettingsCallback() {
                    @Override
                    public void onForwardToSettings(ForwardScope scope, List<String> deniedList) {
                        //这里可以处理被用户永久拒绝的权限
                        scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "我已明白", "取消");
                    }
                })
                .request(new RequestCallback() {
                    @Override
                    public void onResult(boolean allGranted, List<String> grantedList, List<String> deniedList) {
                        if (allGranted) {
                            //申请成功
                            if (requestCallBack != null) requestCallBack.requestSuccess();
                        } else {
                            //申请失败
                            LogX.e(TAG, "权限未全部申请成功");
                            if (requestCallBack instanceof CallBackFail) {
                                if (requestCallBack != null)
                                    ((CallBackFail) requestCallBack).requestFail();
                            }
                        }
                    }
                });
    }

    /**
     * 单权限申请
     */
    public static void requestSingle(Fragment activity, String permission, CallBack requestCallBack) {
        request(activity, requestCallBack, new String[]{permission});
    }

    /**
     * 简易权限申请,一次性全部申请
     * 主要用于启动界面
     */
    public static void requestEasy(Fragment activity, CallBack callBack) {
        request(activity, callBack, NEED_PERMISSIONS);
    }

    /**
     * 申请读写权限
     */
    public static void requestStorage(Fragment activity, CallBack callBack) {
        request(activity, callBack, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE});
    }

    /**
     * 安装未知来源应用
     * 需要在清单文件中申请 REQUEST_INSTALL_PACKAGES
     *
     * @param activity activity
     * @param apkPath apk包的路径
     * @deprecated
     */
    public static void requestInstallApk(Activity activity, String apkPath) {
    }
    //</editor-fold>

    // <editor-fold desc="原生权限申请" defaultstate="collapsed">

    /**
     * 单权限申请,请在申请的Activity中接收回调
     * 使用原生申请需要new 当前实例使用
     * 原生不会处理很多情况，仅申请权限和回调权限是否已申请成功
     *
     * @param activity activiy 拥有回调的权限申请
     * @param permission permission 可使用Manifest里的权限组和单个权限,不能使用第三方依赖的
     * @param requestCode 请求码
     * @param callBack 为null时没有回调
     */
    @TargetApi(23)
    public void requestActivity(Activity activity, @NonNull String permission, int requestCode, @Nullable CallBack callBack) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            LogX.i(TAG, "当前API版本" + Build.VERSION.SDK_INT);
            if (callBack != null) callBack.requestSuccess();
            return;
        }
        // 检查危险权限是否申请
        if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
            //申请权限，返回值使用onRequestPermissionsResult()接收
            requestCallBack = callBack;
            ActivityCompat.requestPermissions(activity,
                    new String[]{permission},
                    requestCode);
            return;
        }
        //权限已同意,直接返回成功
        if (callBack != null) callBack.requestSuccess();
    }

    /**
     * 原生多权限申请,请在申请的Activity中接收回调
     * 使用原生申请需要new 当前实例使用
     * 原生不会处理很多情况，仅申请权限和回调权限是否已申请成功
     *
     * @param activity activiy 拥有回调的权限申请
     * @param permissions permissions 多个权限组
     * @param requestCode 请求码
     * @param callBack 为null时没有回调
     */
    @TargetApi(23)
    public void requestActivity(Activity activity, @NonNull String[] permissions, int requestCode, @Nullable CallBack callBack) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            LogX.i(TAG, "当前API版本" + Build.VERSION.SDK_INT);
            if (callBack != null) callBack.requestSuccess();
            return;
        }
        //权限列表为空返回权限已申请成功
        if (permissions == null || permissions.length == 0) {
            if (callBack != null) callBack.requestSuccess();
            return;
        }
        // 检查权限是否已全部申请
        boolean allGranted = false;
        for (String neededPermission : permissions) {
            allGranted &= ContextCompat.checkSelfPermission(activity, neededPermission) == PackageManager.PERMISSION_GRANTED;
        }
        //还有未申请的去申请
        if (!allGranted) {
            //申请权限，返回值使用onRequestPermissionsResult()接收
            requestCallBack = callBack;
            ActivityCompat.requestPermissions(activity,
                    permissions,
                    requestCode);
            return;
        }
        //权限已同意,直接返回成功
        if (callBack != null) callBack.requestSuccess();
    }

    /**
     * 原生请求权限返回,需要回调使用此方法
     *
     * @param activity 申请权限的activity
     * @param requestCode 请求码
     * @param permissions 权限列表
     * @param grantResults 权限申请结果
     */
    public void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == RequestCode.REQUEST_PERMISSION_CODE) {
            //原生的回调不为空进行判断权限是否已全部同意
            if (requestCallBack != null) {
                List<String> permissionList = new ArrayList<>();
                for (int i = 0; i < permissions.length; i++) {
                    if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                        String permission = permissions[i];
                        //如果用户在过去拒绝了权限请求，并在权限请求系统对话框中选择了 Don't ask again 选项，此方法将返回 false。
                        // 如果设备规范禁止应用具有该权限，此方法也会返回 false。
                        //如果只是单纯拒绝了权限则会返回true
                        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
                            permissionList.add(permission);
                        } else {
                            LogX.w(TAG, "拒绝过权限申请，并选中不再提示");
                            ActivityCompat.requestPermissions(activity, new String[]{permission}, RequestCode.REQUEST_PERMISSION_CODE);
                        }
                    }
                }
                //如果有被拒绝的权限,就是权限申请失败
                if (permissionList.size() > 0) {
                    if (requestCallBack instanceof CallBackFail)
                        ((CallBackFail) requestCallBack).requestFail();
                    return;
                }
                requestCallBack.requestSuccess();
            }
        }
    }


    //</editor-fold>

    // <editor-fold desc="回调接口" defaultstate="collapsed">

    /**
     * 单权限使用此回调
     */
    public interface CallBack {
        void requestSuccess();//请求成功
    }

    /**
     * 实现单个方法的回调类
     *
     * @deprecated use {@link CallBackFail,CallBack}
     */
    public interface CallBackSingle extends CallBack {
        void requestFaile();
    }

    /**
     * 需要失败回调使用
     */
    public interface CallBackFail extends CallBack {
        void requestFail();
    }
//</editor-fold>
}
